
#include "string.h"
#include "led.h"

#define LED_STATE_OFF   0
#define LED_STATE_ON    1

void led_blink_stop(LED_STRUCT* led)
{
	led->blink_times = 0;
	sw_pwm_disable(&(led->sw_pwm));
}

void led_blink_start(LED_STRUCT* led, uint16_t period_time, uint16_t on_time, uint8_t blink_times)
{
	if(period_time > on_time){
		led->blink_times = blink_times;
		sw_pwm_set_compare_1(&(led->sw_pwm), 0);
		sw_pwm_set_compare_2(&(led->sw_pwm), on_time);
		sw_pwm_set_idle_level(&(led->sw_pwm), led->state);
		sw_pwm_set_period(&(led->sw_pwm), period_time);
		sw_pwm_reset_counter(&(led->sw_pwm));
		sw_pwm_enable(&(led->sw_pwm));
	}
}

void led_on(LED_STRUCT* led)
{
	led_blink_stop(led);
    if(led->sw_pwm.set_high_callback != 0){
		led->sw_pwm.set_high_callback();
    }
    led->state = LED_STATE_ON;
}

void led_off(LED_STRUCT* led)
{
	led_blink_stop(led);
    if(led->sw_pwm.set_low_callback != 0){
		led->sw_pwm.set_low_callback();
    }
    led->state = LED_STATE_OFF;
}

void led_toggle(LED_STRUCT* led)
{
	if(led->state == LED_STATE_ON){
		led_off(led);
	}
	else{
		led_on(led);
	}
}

uint8_t led_get_state(LED_STRUCT* led)
{
    return led->state;
}

void led_tick_handler(LED_STRUCT* led, uint16_t ticks)
{
	if(sw_pwm_check_enable(&(led->sw_pwm))){
		sw_pwm_tick_handler(&(led->sw_pwm), ticks);
		if(sw_pwm_check_timeout(&(led->sw_pwm))){
			sw_pwm_reset_timeout(&(led->sw_pwm));
			if((led->blink_times > 0)&&(led->blink_times != 0xff)){
				led->blink_times--;
				if(led->blink_times == 0){
					led_blink_stop(led);
				}
			}
		}
	}
}



void led_group_tick_handler(LED_GROUP_STRUCT* led_group, uint16_t ticks)
{
    static uint8_t i;
    if(ticks > 0){
        for (i = 0; i < led_group->led_num; i++) {
			led_tick_handler(&(led_group->led[i]), ticks);
		}
	}
}

void led_group_init(LED_GROUP_STRUCT* led_group,
						uint8_t led_group_led_num,
						LED_STRUCT* led_space)
{
	memset(led_space, 0, sizeof(LED_STRUCT)*led_group_led_num);
	led_group->led_pointer = 0;
    led_group->led_num = led_group_led_num;
}

LED_STRUCT* led_new(LED_GROUP_STRUCT* led_group,
						void (*led_on_callback)(void),  void (*led_off_callback)(void))
{
    LED_STRUCT* led;
   if(led_group->led_pointer < led_group->led_num){
        led = led_group->led;
		sw_pwm_disable(&(led[led_group->led_pointer].sw_pwm ));
		led[led_group->led_pointer].sw_pwm.set_high_callback = led_on_callback;
		led[led_group->led_pointer].sw_pwm.set_low_callback = led_off_callback;
		led[led_group->led_pointer].blink_times = 0;
		led[led_group->led_pointer].state = LED_STATE_OFF;
        led = &(led[led_group->led_pointer]);
        return led;
    }
    else{
        return 0;
    }
}
